// Comcom_console_s.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <WinSock2.h>
//Also linked ws2_32.lib under project/properties/linker

/////////////////////////////////////////////////////////////
//Forward declarations
/////
char read_command(); //Returns either '\0' on error or char from stdin
void print_menu(int menu_num); //Prints menu to stdin, menu_num decides which menu
int start_server(); //Starts the server (Right now it also starts listening for messages)


/////////////////////////////////////////////////////////////
//DEFINITIONS
/////
#define MENU_MAIN		1
#define MESSAGE_SIZE	1024

/////////////////////////////////////////////////////////////
//MAIN FUNCTION
/////
int _tmain(int argc, _TCHAR* argv[])
{
	//Initialization
	char command = '\0'; //Will use the null char for errors and initialization

	//Initialize Winsock version 2.2
	WSAData wsaData;

	int ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if ( ret != 0){
		//Start up failed!
		printf("WSAStartup failed with error: %d\n", ret);
		return -1; //Error
	}

	//Main loop
	while ( command != 'q'){
		print_menu(MENU_MAIN);
		command = read_command();
		
		//only use the tolower() call if command is a valid character
		if (command != '\0'){
			command = tolower(command);
		}

		switch ( command ){
		case 's':
			//start server
			printf("Starting server...\n");
			printf("Actually, this will both start the server and start listening for messages.\n");
			printf("I will figure out if I want to do the other bit later...\n");
			printf("Probably with a new thread\n");

			ret = start_server();

			if ( ret != 0){
				printf("Error from start_server! Error: %d\n", ret);
			}

			break;
		case 'g':
			//get messages
			printf("Waiting for messages...\n");
			break;
		case 'q':
			//Quit
			printf("Goodbye.\n");
			break;
		default:
			printf("Sorry, that was not a valid command.\n");
		}
	}

	//Call WSACleanup
	ret = WSACleanup();
	if ( ret != 0 ){
		printf("Error with WSACleanup! Error: %d\n", WSAGetLastError());
	}

	return 0;
}

/////////////////////////////////////////////////////////////
//Functions
/////

//READ_COMMAND()
char read_command()
{
	// read_command() will read from stdin and is used when wanting a command
	// read_command() will return a /0 (null) character on error
	// otherwise, read_command() will return the character entered by the user
	char command;
	char junk;

	command = fgetc(stdin);

	if ( command == '\n' ){
		printf("Enter something!\n");
		return '\0';
	}

	junk = fgetc(stdin);
	if ( junk != '\n'){
		// The user entered too many characters
		printf("You entered too many characters!\n");
		command = '\0';
		
		while ( junk != '\n' ){
			// Clear out stdin
			junk = fgetc(stdin);
		}
	}
	return command;
}
//end READ_COMMAND()

//PRINT_MENU()
void print_menu(int menu_num)
{
	switch (menu_num){
	case MENU_MAIN:
		printf("MAIN MENU\n");
		printf("(s)tart server\n");
		printf("(g)et messages\n");
		printf("(q)uit\n");
		printf("=================\n");
		break;
	default:
		printf("Invalid menu number! ERROR! \n");
	}
}
//end PRINT_MENU()

//START_SERVER()
int start_server()
{
	//start_server will get a socket listening
	//Right now it also makes a new connection socket to get messages
	//The return value is 0 if all is good
	//Otherwise the return value will be -1

	SOCKET serverSock; //Used to listen and accept
	SOCKADDR_IN serverAddr; //Holds server information
	int port = 8585; //Random port value
	int ret; //Checks return values

	serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Default arguments
	serverAddr.sin_family = AF_INET; //IPv4
	serverAddr.sin_port = htons(port);
	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

	ret = bind(serverSock, (SOCKADDR *) &serverAddr, sizeof(serverAddr));

	if ( ret != 0){
		printf("Error with bind()! Error: %d\n", WSAGetLastError());
		return -1; //return with error
	}

	printf("Bound server socket...\n");

	ret = listen(serverSock, SOMAXCONN); //Allows for maximum connections

	if ( ret != 0 ){
		printf("Error with listen()! Error: %d\n", WSAGetLastError());
		return -1; //return with error
	}

	printf("Listening on server socket...\n");

	SOCKET connectionSock; //Used to talk with client
	SOCKADDR_IN connectionAddr; //Holds client information
	int connAddrSize = sizeof(connectionAddr);

	printf("Accepting new connection...\n");
	connectionSock = accept(serverSock, (SOCKADDR *) &connectionAddr, &connAddrSize);
	printf("Connection accepted!\n");

	//Now initialize for message receive loop
	char message[MESSAGE_SIZE] = "DEFAULT"; //Buffer for incomming messages
	int messageLen = sizeof(message);
	int nLeft; //Used to keep track of bytes when using recv()
	int idx; //Used to keep track of index when using recv()
	char loopCommand = 'c';

	//Loop as long as user wants to get a new message
	while ( loopCommand != 'q' ){
		nLeft = messageLen;
		idx = 0;

		//Receive entire message
		while ( nLeft > 0 ){
			ret = recv(connectionSock, &message[idx], nLeft, 0);

			if ( ret == SOCKET_ERROR ){
				printf("Error with recv()! Error: %d\n", WSAGetLastError());
				return -1; //return with error
			}
			else if ( ret == 0 ){
				printf("Error! Connection closed!\n");
				return -1; //return with error
			}
			else{
				nLeft -= ret;
				idx += ret;
			}
		}

		printf("Incomming message:\n");
		printf("%s\n", message);

		//Ask user if they want to get another
		printf("Finished with this message.\n");
		printf("Enter 'q' to quit, otherwise enter any other char.\n"); //Check read_command() for \n
		loopCommand = read_command();
	}

	//User is done receiving messages
	//So close sockets
	shutdown(connectionSock, SD_BOTH);
	shutdown(serverSock, SD_BOTH);
	closesocket(connectionSock);
	closesocket(serverSock);

	printf("Finished getting messages from that connection.\n");

	return 0; //return with success
}